package cn.xzqwjw.taskmanager.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.xzqwjw.taskmanager.common.exception.CustomException;
import cn.xzqwjw.taskmanager.common.customEnum.ResponseCodeEnum;
import lombok.extern.slf4j.Slf4j;

import java.awt.*;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.*;

/**
 * 转换工具
 *
 * @author rush
 */
@Slf4j
public class ConvertUtil {

  /**
   * 判断String可否转成Integer
   */
  public static boolean isWrongIntegerString(String numberString) {
    try {
      Integer.parseInt(numberString);
      return false;
    } catch (Exception ex) {
      return true;
    }
  }

  /**
   * 判断String可否转成Long
   */
  public static boolean isWrongLongString(String numberString) {
    try {
      Long.parseLong(numberString);
      return false;
    } catch (Exception ex) {
      return true;
    }
  }

  /**
   * 判断String可否转成Double
   */
  public static boolean isWrongDoubleString(String numberString) {
    try {
      Double.parseDouble(numberString);
      return false;
    } catch (Exception ex) {
      return true;
    }
  }

  /**
   * 判断String可否转成Float
   */
  public static boolean isWrongFloatString(String numberString) {
    try {
      Float.parseFloat(numberString);
      return false;
    } catch (Exception ex) {
      return true;
    }
  }

  /**
   * 判断Obj可否转成Integer
   */
  public static boolean isWrongIntegerObj(Object numberObj) {
    try {
      Integer.parseInt(numberObj.toString());
      return false;
    } catch (Exception ex) {
      return true;
    }
  }

  /**
   * 判断Obj可否转成Long
   */
  public static boolean isWrongLongObj(Object numberObj) {
    try {
      Long.parseLong(numberObj.toString());
      return false;
    } catch (Exception ex) {
      return true;
    }
  }

  /**
   * 将String转成Integer
   */
  public static Integer str2Int(String str) {
    if (isWrongIntegerString(str)) {
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
    return Integer.parseInt(str);
  }

  /**
   * 将String转成Long
   */
  public static Long str2Long(String str) {
    if (isWrongLongString(str)) {
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
    return Long.parseLong(str);
  }

  /**
   * 将String转成Double
   */
  public static Double str2Double(String str) {
    if (isWrongDoubleString(str)) {
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
    return Double.parseDouble(str);
  }

  /**
   * 将String转成Float
   */
  public static Float str2Float(String str) {
    if (isWrongFloatString(str)) {
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
    return Float.parseFloat(str);
  }

  /**
   * 将Object转成Integer
   */
  public static Integer obj2Int(Object obj) {
    CommonUtil.checkNull(obj);
    if (isWrongIntegerObj(obj)) {
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
    return Integer.parseInt(obj.toString());
  }

  /**
   * 将Object转成Long
   */
  public static Long obj2Long(Object obj) {
    CommonUtil.checkNull(obj);
    if (isWrongLongObj(obj)) {
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
    return Long.parseLong(obj.toString());
  }

  /**
   * 将 long 转成 int
   */
  public static int lng2int(long lng) {
    CommonUtil.checkNull(lng);
    if ((int) lng != lng) {
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
    return (int) lng;
  }

  /**
   * 将double转成int
   *
   * @param v         要转换的值
   * @param flagRound 是否进行四舍五入
   */
  public static int double2int(double v, boolean flagRound) {
    if (flagRound) {
      // 3.24 => 3
      // 3.89 => 4
      return (int) Math.round(v);
    } else {
      // 截断小数点后的值，不会四舍五入
      // 3.24 => 3
      // 3.89 => 3
      return (int) v;
    }
  }

  /**
   * 得到 List 的第一个元素
   */
  public static <T> T getListFirst(List<T> list) {
    if (CollUtil.isEmpty(list) || list.size() == 0) {
      return null;
    }
    return list.get(0);
  }

  /**
   * 去除 List 中重复的元素
   */
  public static <T> List<T> clearRepeatList(List<T> list) {
    // 方法一：阿里推荐（使用）
    // 原理是 list 可以允许重复的对象，而 set 不允许重复对象
    // list 可以插入多个 null 元素，而 set 只允许插入一个null元素
    // list是一个有序的容器，保持了每个元素的插入顺序。即输出顺序就是输入顺序
    // 而set方法是无序容器，无法保证每个元素的存储顺序
    // 方法二：这个可以操作数据
    // List<T> tempList = new ArrayList<>();
    // 遍历每个子元素，如果 tempList 中没有则添加
    // for (T t : list) {
    //   if (!tempList.contains(t)) {
    //     tempList.add(t);
    //   }
    // }
    Set<T> set = new HashSet<>(list);
    return new ArrayList<>(set);
  }

  /**
   * 将Object转换成 List<?>
   * List<String> list = object2List(obj, String.Class);
   */
  public static <T> List<T> obj2List(Object obj, Class<T> clazz) {
    List<T> listResult = new ArrayList<>();
    if (obj instanceof List<?>) {
      for (Object o : (List<?>) obj) {
        listResult.add(clazz.cast(o));
      }
      return listResult;
    }
    return null;
  }

  /**
   * pojo转成map
   *
   * @param pojo 要转换的pojo实体对象
   * @return 转换后的Map<String, Object>
   */
  public static <T> Map<String, Object> pojo2Map(T pojo) {
    if (Objects.isNull(pojo)) {
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
    Map<String, Object> result = new HashMap<>(16);
    Method[] methods = pojo.getClass().getMethods();
    try {
      for (Method method : methods) {
        Class<?>[] paramClass = method.getParameterTypes();
        // 如果方法带参数，则跳过
        if (paramClass.length > 0) {
          continue;
        }
        String methodName = method.getName();
        if (methodName.startsWith("get")) {
          Object value = method.invoke(pojo);
          result.put(methodName, value);
        }
      }
    } catch (IllegalArgumentException |
             IllegalAccessException |
             InvocationTargetException |
             SecurityException e) {
      log.error("pojo2Map() 报错：{}", e.getMessage());
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
    return result;
  }

  /**
   * map转成pojo
   *
   * @param map   要转换的map
   * @param clazz 要转换的pojo实体对象的class
   * @return 转换后的pojo
   */
  public static Object mapToPojo(Map<?, ?> map, Class<?> clazz) {
    if (Objects.isNull(map) || Objects.isNull(clazz)) {
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
    Object obj;
    try {
      BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
      obj = clazz.getDeclaredConstructor().newInstance();
      PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
      for (PropertyDescriptor descriptor : propertyDescriptors) {
        String propertyName = descriptor.getName();
        if (map.containsKey(propertyName)) {
          Object value = map.get(propertyName);
          descriptor.getWriteMethod().invoke(obj, value);
        }
      }
    } catch (Exception e) {
      log.error("mapToPojo() 报错：{}", e.getMessage());
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
    return obj;
  }

  /**
   * #e3bea8 形式的字符串转成 color 对象
   *
   * @param str 必须以"#"开头的字符串，例如 #e3bea8
   */
  public static Color str2Color(String str) {
    if (!StrUtil.isBlank(str) || str.length() != 7 || !str.startsWith("#")) {
      return null;
    }
    try {
      int i = Integer.parseInt(str.substring(1), 16);
      return new Color(i);
    } catch (Exception e) {
      return null;
    }
  }

  /**
   * color 对象转成 #e3bea8 形式的字符串
   */
  public static String color2Str(Color color) {
    String R = Integer.toHexString(color.getRed());
    R = R.length() < 2 ? ('0' + R) : R;
    String B = Integer.toHexString(color.getBlue());
    B = B.length() < 2 ? ('0' + B) : B;
    String G = Integer.toHexString(color.getGreen());
    G = G.length() < 2 ? ('0' + G) : G;
    return "#" + R + B + G;
  }

}
